import type { FormItemTemplateConfig } from '@/components/template/form-item/form-item-template.vue';
import { message } from 'ant-design-vue';
import { type UploadFile } from 'ant-design-vue';
import { type Rule } from 'ant-design-vue/es/form';
import type { ValidateInfo } from 'ant-design-vue/es/form/useForm';

export const FileUtil = {
  /**
   * 判断文件上传的数据是否小于某个值 （单位 M）
   * @param file 上传的文件
   * @param max 最大值
   * @returns 如果文件大小小于最大值，则返回true；否则返回false
   */
  isLtNum: (file: UploadFile, max: number) => {
    return file.size !== undefined && file.size / 1024 / 1024 < max;
  },
};

/**
 * 表单工具类
 */
export const FormUtil = {
  /**
   * 根据接口中的错误信息获取表单验证信息
   */
  getValidateInfoByApiError: (str: string) => {
    // (\w+)：匹配括号内的字母、数字或下划线（字段名的组成部分）
    const regExp = /\[(\w+)\]/g;
    const matches = str.match(regExp);
    if (!matches) {
      return null;
    }

    // 提取错误描述
    const errorMessages = str.split('错误描述：')[1].split(';');

    return matches.reduce((validateInfo: Record<string, ValidateInfo>, match) => {
      const prefix = `字段${match}错误:`;
      const fieldName = match.replace(/[\[\]]/g, '');
      const errorMessage = errorMessages.find((message) => message.includes(prefix));

      validateInfo[fieldName] = {
        validateStatus: 'error',
        help: errorMessage!.replace(prefix, ''),
      };
      return validateInfo;
    }, {});
  },
};

/**
 * 规则工具类
 */
export const Rules = {
  /**
   * 获取规则消息
   * @param item 表单配置项
   * @returns 规则消息
   */
  getRequiredRuleMessage: (item: FormItemTemplateConfig) => {
    const selectTypeList: FormItemTemplateConfig['type'][] = [
      'tree-select',
      'select',
      'multiple-select',
      'cascader',
      'checkbox',
      'radio',
    ]; // 选择类组件
    const inputTypeList: FormItemTemplateConfig['type'][] = ['input', 'input-number', 'icon-select', 'textarea']; // 输入类组件
    const uploadTypeList: FormItemTemplateConfig['type'][] = ['upload']; // 上传类组件

    if (selectTypeList.includes(item.type)) {
      return `请选择${item.title}`; // 选择类：请选择XX（如“请选择上级模块”）
    } else if (inputTypeList.includes(item.type)) {
      return `请输入${item.title}`; // 输入类：请输入XX（如“请输入模块名称”）
    } else if (uploadTypeList.includes(item.type)) {
      return `请上传${item.title}`; // 上传类：请输入XX（如“请上传模块名称”）
    }
    return ''; // 未匹配到的组件无法给出提示
  },
  /**
   * 获取通用必填规则
   * @param msg 错误提示消息
   * @param extra 额外的规则配置
   * @returns 规则数组
   */
  getRequiredRules: (msg: string, extra?: Rule): Rule[] => [{ required: true, message: msg, ...extra }],
  /**
   * 获取文件上传必填规则
   * @param msg 错误提示消息
   * @returns 规则数组
   */
  getRequiredUploadRules: (msg: string): Rule[] => [
    {
      required: true,
      message: msg,
      validator(_, files: UploadFile[] = []) {
        for (const file of files) {
          // 如果上传文件没有完成上传或者上传失败，则返回错误
          if (file?.status !== 'done' || file?.response?.biz_content?.sub_code !== 100000) {
            file.status = 'error';
            return Promise.reject();
          }
        }
        return Promise.resolve();
      },
    },
  ],
  /**
   * 获取必填规则
   * @param title 模块名称
   * @param uploadMaxSize 大小限制：单位 MB
   * @returns 规则数组
   */
  getUploadFileMaxSizeRules: (title: string, uploadMaxSize: number): Rule[] => [
    {
      message: `${title}大小超过限制 ${uploadMaxSize} MB`,
      validator(_, files: UploadFile[] = []) {
        for (const file of files) {
          if (!FileUtil.isLtNum(file, uploadMaxSize)) {
            file.status = 'error';
            return Promise.reject();
          }
        }
        return Promise.resolve();
      },
    },
  ],
};

/**
 * 本地存储工具类
 */
export const LocalStorage = (() => {
  const prefix = 'app_';
  return {
    /**
     * 存储键值对到本地存储
     * @param key 键
     * @param value 值
     */
    set: (key: string, value: string | null) => {
      localStorage.setItem(prefix + key, value || '');
    },
    /**
     * 从本地存储获取值
     * @param key 键
     * @returns 值
     */
    get: (key: string) => {
      return localStorage.getItem(prefix + key);
    },
    /**
     * 从本地存储移除键值对
     * @param key 键
     */
    remove: (key: string) => {
      localStorage.removeItem(prefix + key);
    },
    /**
     * 清除本地存储
     */
    clear: () => {
      localStorage.clear();
    },
  };
})();

/*
 * 字符串工具类
 */
export const StringUtil = {
  /**
   * 复制文本到剪贴板
   * @param content 要复制的文本内容
   */
  copyToClipboard: async (content: string) => {
    try {
      await navigator.clipboard.writeText(content);
      message.success('复制成功');
    } catch (error) {
      // 兼容旧浏览器的降级方案
      const textarea = document.createElement('textarea');
      textarea.value = content;
      textarea.style.position = 'fixed'; // 避免滚动影响
      document.body.appendChild(textarea);
      textarea.select();
      try {
        const successful = document.execCommand('copy');
        if (successful) {
          message.success('复制成功');
        } else {
          message.error('复制失败，请手动复制');
        }
      } catch (err) {
        message.error('复制失败，请手动复制');
      } finally {
        document.body.removeChild(textarea);
      }
    }
  },
  /**
   * 检查字符串是否为空
   * @param str 要检查的字符串
   * @returns 如果字符串为空或只包含空格，则返回true；否则返回false
   */
  isEmpty: (str: string) => {
    return str.trim().length === 0;
  },
};
